#pragma once
#include <iostream>
#include <unordered_map>
#include <vector>
#include <fstream>
#include <assert.h>
#include <mutex>

#include "../com/util.hpp"
#include "../com/log.hpp"
namespace lh_model
{
    using namespace lh_util;
    using namespace lh_log;
    static std::string host_conf = "./conf/hostlist.conf";
    struct Question
    {
        std::string number; // 题目编号
        std::string title;  // 题目名称
        std::string level;  // 题目难度等级
        int climit; // 题目时间限制
        int mlimit; // 题目空间限制
        std::string desc;   // 题目描述
        std::string header; // 题目预设值代码
        std::string tail;   // 题目运行代码
    };
    static std::string questionslist_path = "./questions/question_list.text";
    static std::string question_path = "./questions/";
    static std::string desc_path = "desc.text";
    static std::string header_path = "header.cpp";
    static std::string tail_path = "tail.cpp";
    static std::string sep = " ";
    class Model
    {
    public:
        Model()
        {
            assert(LoadQuestionsList());
            // assert(LoadQuestionsList());
        }
        ~Model() {}
        bool LoadQuestionsList()
        {
            // 将所有题目加载到内存中
            std::ifstream in(questionslist_path);
            if (!in.is_open())
                return 0;
            std::string str;
            while (getline(in, str))
            {
                // 字符串分割
                // "1 回文字符串 简单 1 30000" -> "1" "回文字符串" "简单" "1" "30000"
                std::vector<std::string> target;
                StringUtil::Split(str, &target, sep);
                Question qst;           // 题目
                qst.number = target[0]; // 题目编号
                qst.title = target[1];  // 题目标题
                qst.level = target[2];  // 题目等级
                qst.climit = stoi(target[3]); // 时间限制
                qst.mlimit = stoi(target[4]); // 空间限制
                std::string path = question_path + qst.number;
                path += "/";
                FileUtil::ReadFile(path + desc_path, &qst.desc, true);     // 题目描述
                FileUtil::ReadFile(path + header_path, &qst.header, true); // 预设值代码
                FileUtil::ReadFile(path + tail_path, &qst.tail, true);     // 运行代码
                _questions.insert({qst.number, qst});
            }
            return 1;
        }
        bool GetAllQuestion(std::vector<Question> *questions)
        {
            if (_questions.size() == 0)
                return false;
            for (auto &e : _questions)
            {
                questions->push_back(e.second);
            }
            return true;
        }
        bool GetQuestionByNumber(const std::string &number, Question *out)
        {
            auto iter = _questions.find(number);
            if (iter == _questions.end())
                return false;
            *out = iter->second;
            return true;
        }
    private:
        std::unordered_map<std::string, Question> _questions;
    };
}